//////////////////////////////////////////ok
#include"stdafx.h"
#include "bochs.h"



void IA32_CPU::INSB_YbDX(Ia32_Instruction_c *i)
{
  Bit8u value8=0;

  if ( cr0.pe && ( get_VM () || (CPL> get_IOPL ()))) 
  {
    if (!allow_io(DX, 1)) 
	{
      exception(IA32_GP_EXCEPTION, 0, 0);
    }
  
  }

   if (i->as32L()) 
   {
		write_virtual_byte(IA32_SEG_REG_ES, EDI, &value8);
		
		// value8 = BX_INP(DX, 1);
		
		write_virtual_byte(IA32_SEG_REG_ES, EDI, &value8);
		
		if ( get_DF ()) 
		{
			EDI = EDI - 1;
		}
		else 
		{
			EDI = EDI + 1;
		}
  }
  else 
  {
    write_virtual_byte(IA32_SEG_REG_ES, DI, &value8);

   // value8 = BX_INP(DX, 1);

    /* no seg override possible */
    write_virtual_byte(IA32_SEG_REG_ES, DI, &value8);

    if ( get_DF ())
      DI--;
    else
      DI++;
  }

}

void IA32_CPU::INSW_YvDX(Ia32_Instruction_c *i)
{
  ia32_address edi;
  unsigned int incr;

   if (i->as32L())
    edi = EDI;
  else
    edi = DI;

  if (i->os32L()) 
  {
    Bit32u value32=0;

    if ( cr0.pe && ( get_VM () || (CPL> get_IOPL ()))) 
	{
      if ( ! allow_io(DX, 4) ) 
	  {
        exception(IA32_GP_EXCEPTION, 0, 0);
      }
    }

    write_virtual_dword(IA32_SEG_REG_ES, edi, &value32);

   // value32 = BX_INP(DX, 4);

    write_virtual_dword(IA32_SEG_REG_ES, edi, &value32);
    incr = 4;
  }
  else 
  {
    Bit16u value16=0;
    if ( cr0.pe && ( get_VM () || (CPL> get_IOPL ()))) 
	{
      if ( ! allow_io(DX, 2) )
        exception(IA32_GP_EXCEPTION, 0, 0);
    }

    write_virtual_word(IA32_SEG_REG_ES, edi, &value16);

    //value16 = BX_INP(DX, 2);

    write_virtual_word(IA32_SEG_REG_ES, edi, &value16);
    incr = 2;
  }

  if (i->as32L()) 
  {
    if ( get_DF ())
      EDI = EDI - incr;
    else
      EDI = EDI + incr;
  }
  else 
  {
    if ( get_DF ())
      DI = DI - incr;
    else
      DI = DI + incr;
  }

}

void IA32_CPU::OUTSB_DXXb(Ia32_Instruction_c *i)
{
  unsigned seg;
  Bit8u value8;
  ia32_address esi;

  if ( cr0.pe && ( get_VM () || (CPL> get_IOPL ()))) 
  {
    if (!allow_io(DX, 1)) 
	{
      exception(IA32_GP_EXCEPTION, 0, 0);
    }
  }

  if (!IA32_NULL_SEG_REG(i->seg())) 
  {
    seg = i->seg();
  }
  else 
  {
    seg = IA32_SEG_REG_DS;
  }

  if (i->as32L())
    esi = ESI;
  else
    esi = SI;

  read_virtual_byte(seg, esi, &value8);

 // BX_OUTP(DX, value8, 1);

  if (i->as32L()) 
  {
    if ( get_DF ())
      ESI--;
    else
      ESI++;
  }
  else 
  {
    if ( get_DF ())
      SI--;
    else
      SI++;
  }

}

void IA32_CPU::OUTSW_DXXv(Ia32_Instruction_c *i)
{
  unsigned seg;
  ia32_address esi;
  unsigned int incr;

  if (!IA32_NULL_SEG_REG(i->seg())) 
  {
    seg = i->seg();
  }
  else 
  {
    seg = IA32_SEG_REG_DS;
  }

  if (i->as32L())
    esi = ESI;
  else
    esi = SI;

  if (i->os32L()) 
  {
    Bit32u value32;

    if ( cr0.pe && ( get_VM () || (CPL> get_IOPL ()))) 
	{
      if ( ! allow_io(DX, 4) ) 
	  {
        exception(IA32_GP_EXCEPTION, 0, 0);
      }
    }

    read_virtual_dword(seg, esi, &value32);

    //BX_OUTP(DX, value32, 4);
    incr = 4;
  }
  else 
  {
    Bit16u value16;

    if ( cr0.pe && ( get_VM () || (CPL> get_IOPL ()))) 
	{
      if ( ! allow_io(DX, 2) ) 
	  {
        exception(IA32_GP_EXCEPTION, 0, 0);
      }
    }

    read_virtual_word(seg, esi, &value16);

    //BX_OUTP(DX, value16, 2);
    incr = 2;
  }

  if (i->as32L()) 
  {
    if ( get_DF ())
      ESI = ESI - incr;
    else
      ESI = ESI + incr;
  }
  else 
  {
    if ( get_DF ())
      SI = SI - incr;
    else
      SI = SI + incr;
  }

}

void IA32_CPU::IN_ALIb(Ia32_Instruction_c *i)
{
  AL =  inp8(i->Ib());
}

void IA32_CPU::IN_eAXIb(Ia32_Instruction_c *i)
{
  if (i->os32L()) 
  {
    Bit32u eax =  inp32(i->Ib());
    EAX = eax;
  }
  else
  {
    AX =  inp16(i->Ib());
  }
}

void IA32_CPU::OUT_IbAL(Ia32_Instruction_c *i)
{
   outp8(i->Ib(), AL);
}

void IA32_CPU::OUT_IbeAX(Ia32_Instruction_c *i)
{
  if (i->os32L()) 
  {
     outp32(i->Ib(), EAX);
  }
  else
  {
     outp16(i->Ib(), AX);
  }

}

void IA32_CPU::IN_ALDX(Ia32_Instruction_c *i)
{
  AL =  inp8(DX);
}

void IA32_CPU::IN_eAXDX(Ia32_Instruction_c *i)
{
  if (i->os32L()) 
  {
    Bit32u eax =  inp32(DX);
    EAX = eax;
  }
  else
  {
    AX =  inp16(DX);
  }
}

void IA32_CPU::OUT_DXAL(Ia32_Instruction_c *i)
{
   outp8(DX, AL);
}

void IA32_CPU::OUT_DXeAX(Ia32_Instruction_c *i)
{
  if (i->os32L()) 
  {
     outp32(DX, EAX);
  }
  else
  {
     outp16(DX, AX);
  }
}
